<?php
/**
 * User: Titan
 * Date: Sep 28, 2010
 * Time: 10:07:39 PM
 */

/**
 * render()
 * 
 * An excellent function that finds the best way to render an object 
 * (page function, system function, or, in the case of render('page') calls, a template file)
 * 
 * This function takes a variable number of arguments.
 * 
 * The first argument is always the name of the object you are rendering--for example, 'page'.
 * 
 * The remaining arguments are anything that should be passed to the rendering function or template
 * 
 * @return the rendered HTML content
 */
function render()
{
	$args = func_get_args();
	$model = array_shift($args);
	
	static $models = array();
	
	$output = '';
	
	// check to see if a rendering method has been used for this specific model
	// ie. for form elements. render('submit') is called a lot so it's unnecessary to search for it again
	if (isset($models[$model]))
	{
		$details = $models[$model];
		if (isset($details['template']))
		{
			// rendering the page
			$args[$model] = $args[0];
			
			// call the template's prerendering functions
			render_call_prerender($args, $model);
			
			// make sure the file exists before rendering it
			if (file_exists('./' . $args['template']))
			{
				$output = render_template($args['template'], $args);
			}
		}
		else if (isset($details['function']))
		{
			// use a rendering function, and make sure it exists
			if (function_exists($details['function']))
			{
				$output = call_user_func_array($details['function'], $args);
			}
		}
	}
	else
	{
		// use the loaded page's rendering functions
		// this is useful because different pages will have different rendering functions
		// ie. a page that lists developers will want different content than a
		// page that lists milestones
		global $load;
		
		if (function_exists($load . '_' . $model))
		{
			$output = call_user_func_array($load . '_' . $model, $args);
			$models[$model]['function'] = $load . '_' . $model;
		}
		else if (file_exists('./templates/' . $model . '.tpl.php'))
		{
			$args[$model] = './templates/' . $model . '.tpl.php';
			if (isset($args[0]))
			{
				$args = array_merge($args[0], $args);
				unset($args[0]);
			}
			
			render_call_prerender($args, $model);
			$output = render_template('./templates/' . $model . '.tpl.php', $args);
			$models[$model]['template'] = './templates/' . $model . '.tpl.php';
		}
		else if (function_exists('render_' . $model))
		{
			$output = call_user_func_array('render_' . $model, $args);
			$models[$model]['function'] = 'render_' . $model;
		}
	}

	return $output;
}

/**
 * Theme a heading (ie. <h1> element).
 * 
 * @param $text: the text to be included in the heading. Not translated here.
 * @param $level: the level of the heading (1 - 6).
 * @param $attributes: Optional attributes.
 * @return themed heading.
 */
function render_heading($text, $level = 2, $attributes = array())
{
	if ($level > 6 || $level < 1)
	{
		system_set_message('Invalid heading level requested ' . $level, 'error');
		$level = 6;
	}

	return "<h$level " . render_attributes($attributes) . '>' . $text . "</h$level>";
}

/**
 * render_attributes()
 * 
 * This is a function that will take in a key => value array 
 * and produce a string of HTML attributes.
 * 
 * ie. an array like array('class' => 'navigation') will return ' class="navigation"'
 * 
 * @param mixed $attributes
 * @return
 */
function render_attributes($attributes = array())
{
	if (is_array($attributes))
	{
		$output = '';
		foreach ($attributes as $key => $value)
		{
			$output .= " $key=" . '"' . html_safe($value) . '"';
		}

		return $output;
	}
}

/**
 * render_html_class()
 * 
 * Prepare a string for use as a valid class name.
 *
 * @param $class
 *   The class name to clean.
 * @return
 *   The cleaned class name.
 */
function render_html_class($class)
{
	return render_clean_css_identifier(strtolower($class));
}

/**
 * render_clean_css_identifier()
 * 
 * Prepare a string for use as a valid CSS identifier (element, class or ID name).
 *
 * @param $identifier
 *   The identifier to clean.
 * @param $filter
 *   An array of string replacements to use on the identifier.
 * @return
 *   The cleaned identifier.
 */
function render_clean_css_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '/' => '-', '[' => '-', ']' => ''))
{
	// By default, we filter using Drupal's coding standards.
	$identifier = strtr($identifier, $filter);

	// Valid characters in a CSS identifier are:
	// - the hyphen (U+002D)
	// - a-z (U+0030 - U+0039)
	// - A-Z (U+0041 - U+005A)
	// - the underscore (U+005F)
	// - 0-9 (U+0061 - U+007A)
	// - ISO 10646 characters U+00A1 and higher
	// We strip out any character not in the above list.
	$identifier = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', $identifier);

	return $identifier;
}

/**
 * render_unique_id()
 * 
 * Guarantee a unique ID for the page element the page
 * 
 * This function is only useful if everytime an HTML id is used, that id
 * is checked through this function before rendering
 * 
 * @param mixed $id
 * @return
 */
function render_unique_id($id)
{
	static $built_ids = array();

	$id = strtr(strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
	$id = preg_replace(array('/[^A-Za-z0-9\-_]/', '/\-+/'), array('', '-'), $id);

	if (isset($built_ids[$id]))
	{
		$id = $id . '-' . $built_ids[$id]++;
	}
	else
	{
		$built_ids[$id] = 1;
	}

	return $id;
}

/**
 * render_template()
 * 
 * This function gets the HTML content of a template file (ie. page.tpl.php)
 * 
 * @param mixed $file
 * @param mixed $vars
 * @return
 */
function render_template($file, $vars = array())
{
	extract($vars);

	ob_start();
	include('./' . $file);

	return ob_get_clean();
}

/**
 * render_call_prerender()
 * 
 * This function calls any prerender functions that are defined by the system or the loading page 
 * 
 * @param mixed $variables
 * @param mixed $function
 * @return void
 */
function render_call_prerender(&$variables, $function)
{
	global $load;
	
	$parameters = array(&$variables, $function);
	
	$sys_function = 'system_prerender_' . $function;
	if (function_exists($sys_function))
	{
		call_user_func_array($sys_function, $parameters);
	}

	$page_function = $load . '_prerender_' . $function;
	if (function_exists($page_function))
	{
		call_user_func_array($page_function, $parameters);
	}

	$system_clean_function = 'system_prerender_cleanup_' . $function;
	if (function_exists($system_clean_function))
	{
		call_user_func_array($system_clean_function, $parameters);
	}
}

/**
 * render_generic_button()
 * 
 * This function renders a <button> element
 * 
 * @param mixed $button
 * @return
 */
function render_generic_button($button)
{
	$output = '<button id="' . $button['#id'] . '"' . (isset($button['#title']) ? ' title="' . $button['#title'] . '"' : '') . ' type="button"' . (isset($button['#disabled']) && $button['#disabled'] ? ' disabled="disabled"' : '') . (empty($button['#attributes']) ? '' : render_attributes($button['#attributes'])) . '>' . html_safe($button['#title']) . '</button>' . "\n";
	$prefix = (isset($button['#prefix']) ? $button['#prefix'] : '');
	$suffix = (isset($button['#suffix']) ? $button['#suffix'] : '');
	
	return $prefix . $output . $suffix;
}

/**
 * render_system_messages()
 * 
 * @param mixed $messages
 * @return
 */
function render_system_messages($messages)
{
	$output = '';
	foreach ($messages as $type => $message_list) 
	{
		if (!empty($message_list))
		{
			$output .= '<div class="' . $type . '"><ul>' . "\n";
			
			for ($i = 0; $i < count($message_list); $i++)
			{
				$output .= '<li class="message">' . $messages[$type][$i] . '</li>' . "\n";
			}
			
			$output .= '</ul></div>' . "\n";
		}
	}
	
	return $output;
}

function render_table($table)
{
	$output = '<table' . (empty($table['#attributes']) ? '' : render_attributes($table['#attributes'])) . '>';
	
	if (isset($table['#header']) && count($table['#header']) > 0)
	{
		$output .= '<thead><tr>';
		
		foreach ($table['#header'] as $cell)
		{
			$output .= render_table_cell($cell, NULL, TRUE);
		}
		
		$output .= '</tr></thead>';
	}
			
	if (isset($table['#rows']) && count($table['#rows']) > 0)
	{
		$output .= '<tbody>';
		
		$row_count = count($table['#rows']);
		foreach ($table['#rows'] as $index => $row)
		{
			$classes = array((($index + 1) % 2 == 0 ? 'even' : 'odd'));
			if ($index == 0)
			{
				$classes[] = 'first';
			}
			else if ($index == $row_count - 1)
			{
				$classes[] = 'last';
			}
			
			$output .= '<tr class="' . implode(' ', $classes) . '"' . (empty($row['#attributes']) ? '' : render_attributes($row['#attributes'])) . '>';
			
			if (isset($row['#cells']))
			{
				foreach ($row['#cells'] as $key => $cell)
				{
					$output .= render_table_cell($cell, $key);
				}
			}
			
			$output .= '</tr>';
		}
		
		$output .= '</tbody>';
	}
	
	$output .= '</table>' . "\n";
	
	return $output;
}

/**
 * render_table_cell()
 * 
 * @param mixed $cell
 * @param bool $header
 * @return
 */
function render_table_cell($cell, $key = NULL, $header = FALSE)
{
	$tag = 'td';
	if ($header)
	{
		$tag = 'th';
	}
	
	if (is_array($cell))
	{
		if (!empty($key))
		{
			if (empty($cell['#attributes']))
			{
				$cell['#attributes'] = array('class' => $key);
			}
			else 
			{
				if (empty($cell['#attributes']['class']))
				{
					$cell['#attributes']['class'] = $key;
				}
				else 
				{
					$cell['#attributes']['class'] .= ' ' . $key;
				}
			}
		}
		
		return '<' . $tag . (empty($cell['#attributes']) ? '' : render_attributes($cell['#attributes'])) . '>' . $cell['#value'] . '</' . $tag . '>' . "\n";
	}
	else 
	{
		return '<' . $tag . (empty($key) ? '' : ' class="' . render_html_class($key) . '"') . '>' . $cell . '</' . $tag . '>' . "\n";
	}
}

function render_breadcrumbs($breadcrumbs)
{
	$output = '';
	if (!empty($breadcrumbs))
	{
		$separator = '</li><li class="breadcrumb"> > </li><li class="breadcrumb">';
		
		$output = '<div class="breadcrumbs"><ul><li class="breadcrumb first">' . implode($separator, $breadcrumbs) . '</li><li class="breadcrumb"> > </li><li class="breadcrumb last">' . system_page_title() . '</li></ul></div>';
	}
	
	return $output;
}
















